package me.zhangsanfeng.gpss.common.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.sf.cglib.beans.BeanMap;

/**
 * Map工具类<br>
 */
public class MapUtils{
    private static final char SEPARATOR='_';

    @SuppressWarnings("unchecked")
    public static <T> T map2Bean(Map<String,Object> map,T bean){
        String jsonString=JsonUtil.toJsonString(map);
        return (T)JsonUtil.fromJsonString(jsonString,bean.getClass());
    }

    @SuppressWarnings("unchecked")
    public static <T> T map2Bean(Map<String,Object> map,Class<T> classz){
        String jsonString=JsonUtil.toJsonString(map);
        return (T)JsonUtil.fromJsonString(jsonString,classz);
    }

    /**
     * 将List<T>转换为List<Map<String, Object>>
     * @param
     * @return
     * @throws JsonGenerationException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static <T> T mapToBean(Map<String,Object> map,T bean){
        BeanMap beanMap=BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }

    /**
     * 将List<T>转换为List<Map<String, Object>>
     * @param
     * @return
     * @throws JsonGenerationException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static <T> Map<String,Object> beanToMap(T obj){
        if(obj==null){
            return null;
        }
        Map<String,Object> map=Maps.newHashMap();
        if(obj!=null){
            BeanMap beanMap=BeanMap.create(obj);
            for(Object key:beanMap.keySet()){
                map.put(key+"",beanMap.get(key));
            }
        }
        return map;
    }

    @SuppressWarnings("unchecked")
    public static <T> Map<String,Object> bean2Map(T obj){
        if(obj==null){
            return null;
        }
        String jsonString=JsonUtil.toJsonString(obj);
        return (Map<String,Object>)JsonUtil.fromJsonString(jsonString,Map.class);
    }

    /**
     * 将List<T>转换为List<Map<String, Object>>
     * @param objList
     * @return
     * @throws JsonGenerationException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static <T> List<Map<String,Object>> objectsToMaps(List<T> objList){
        List<Map<String,Object>> list=Lists.newArrayList();
        if(objList!=null&&objList.size()>0){
            Map<String,Object> map=null;
            T bean=null;
            for(int i=0,size=objList.size();i<size;i++){
                bean=objList.get(i);
                map=beanToMap(bean);
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 将List<Map<String,Object>>转换为List<T>
     * @param maps
     * @param clazz
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> List<T> mapsToObjects(List<Map<String,Object>> maps,Class<T> clazz){
        List<T> list=Lists.newArrayList();
        if(maps!=null&&maps.size()>0){
            Map<String,Object> map=null;
            T bean=null;
            for(int i=0,size=maps.size();i<size;i++){
                map=maps.get(i);
                try{
                    bean=clazz.newInstance();
                }catch(InstantiationException e){
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }catch(IllegalAccessException e){
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                list.add(map2Bean(map,bean));
            }
        }
        return list;
    }

    /**
     * 将Map的Keys去下划线<br>
     * (例:branch_no -> branchNo )<br>
     * @param map 待转换Map
     * @return
     */
    public static <V> Map<String,V> toCamelCaseMap(Map<String,V> map){
        Map<String,V> newMap=new HashMap<String,V>();
        for(String key:map.keySet()){
            newMap.put(toCamelCaseString(key),map.get(key));
        }
        return newMap;
    }

    /**
     * 将Map的Keys转译成下划线格式的<br>
     * (例:branchNo -> branch_no)<br>
     * @param map 待转换Map
     * @return
     */
    public static <V> Map<String,V> toUnderlineStringMap(Map<String,V> map){
        Map<String,V> newMap=new HashMap<String,V>();
        for(String key:map.keySet()){
            newMap.put(toUnderlineString(key),map.get(key));
        }
        return newMap;
    }

    /**
     * 方法名称:transMapToString 传入参数:map 返回值:String 形如 username'chenziwen^password'1234
     */
    public static String transMapToString(Map<String,String> map){
        Entry<String,String> entry;
        StringBuffer sb=new StringBuffer();
        for(Iterator<Entry<String,String>> iterator=map.entrySet().iterator();iterator.hasNext();){
            entry=iterator.next();
            sb.append(entry.getKey().toString()).append("'").append(null==entry.getValue() ? ""
                    : entry.getValue().toString()).append(iterator.hasNext() ? "^" : "");
        }
        return sb.toString();
    }

    /**
     * 方法名称:transStringToMap 传入参数:mapString 形如 username'chenziwen^password'1234 返回值:Map
     */
    public static Map<String,String> transStringToMap(String mapString){
        Map<String,String> map=new HashMap<String,String>();
        StringTokenizer items;
        for(StringTokenizer entrys=new StringTokenizer(mapString,"^");entrys.hasMoreTokens();map.put(items
                .nextToken(),items.hasMoreTokens() ? ((items.nextToken())) : null))
            items=new StringTokenizer(entrys.nextToken(),"'");
        return map;
    }

    /**
     * 将属性样式字符串转成驼峰样式字符串<br>
     * (例:branchNo -> branch_no)<br>
     * @param inputString
     * @return
     */
    public static String toUnderlineString(String inputString){
        if(inputString==null)
            return null;
        StringBuilder sb=new StringBuilder();
        boolean upperCase=false;
        for(int i=0;i<inputString.length();i++){
            char c=inputString.charAt(i);
            boolean nextUpperCase=true;
            if(i<(inputString.length()-1)){
                nextUpperCase=Character.isUpperCase(inputString.charAt(i+1));
            }
            if((i>=0)&&Character.isUpperCase(c)){
                if(!upperCase||!nextUpperCase){
                    if(i>0)
                        sb.append(SEPARATOR);
                }
                upperCase=true;
            }else{
                upperCase=false;
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    /**
     * 将驼峰字段转成属性字符串<br>
     * (例:branch_no -> branchNo )<br>
     * @param inputString 输入字符串
     * @return
     */
    public static String toCamelCaseString(String inputString){
        return toCamelCaseString(inputString,false);
    }

    /**
     * 将驼峰字段转成属性字符串<br>
     * (例:branch_no -> branchNo )<br>
     * @param inputString 输入字符串
     * @param firstCharacterUppercase 是否首字母大写
     * @return
     */
    public static String toCamelCaseString(String inputString,boolean firstCharacterUppercase){
        if(inputString==null)
            return null;
        StringBuilder sb=new StringBuilder();
        boolean nextUpperCase=false;
        for(int i=0;i<inputString.length();i++){
            char c=inputString.charAt(i);
            switch(c){
            case '_':
            case '-':
            case '@':
            case '$':
            case '#':
            case ' ':
            case '/':
            case '&':
                if(sb.length()>0){
                    nextUpperCase=true;
                }
                break;
            default:
                if(nextUpperCase){
                    sb.append(Character.toUpperCase(c));
                    nextUpperCase=false;
                }else{
                    sb.append(Character.toLowerCase(c));
                }
                break;
            }
        }
        if(firstCharacterUppercase){
            sb.setCharAt(0,Character.toUpperCase(sb.charAt(0)));
        }
        return sb.toString();
    }

    /**
     *
     * @param map
     * @param filterKey
     * @param isTrue
     * @param <V>
     * @return
     */
    public static <V> Map<String,V> filterMapKey(Map<String,V> map,String filterKey,boolean isTrue){
        return Maps.filterKeys(map,new Predicate<String>(){
            @Override
            public boolean apply(String s){
                if(filterKey.contains(s)){
                    return isTrue;
                }else{
                    return !isTrue;
                }
            }
        });
    }

    public static <V> Map<String,V> filterMapKey(Map<String,V> map,String filterKey){
        return filterMapKey(map,filterKey,true);
    }
}
